//
//  XPQLabel.h
//  XPQLabel
//
//  Created by XPQ on 15/10/12.
//  Copyright © 2015年 com.xpq. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <CoreText/CoreText.h>
#import "XPQLabelPath.h"

typedef enum : NSUInteger {
    XPQLabelHorizontalAlignmentLeft,
    XPQLabelHorizontalAlignmentCenter,
    XPQLabelHorizontalAlignmentRight,
} XPQLabelHorizontalAlignment;

typedef enum : NSUInteger {
    XPQLabelVerticalAlignmentUp,
    XPQLabelVerticalAlignmentCenter,
    XPQLabelVerticalAlignmentDown,
} XPQLabelVerticalAlignment;

@interface XPQLabel : UIView
/**
 *  要显示的文本。
 */
@property(nonatomic, copy) IBInspectable NSString *text;
/**
 *  文本颜色。
 */
@property(nonatomic, strong) IBInspectable UIColor *textColor;
/**
 *  文本字体。
 */
@property(nonatomic, strong) UIFont *font;
/**
 *  富文本。
 */
@property(nonatomic, copy)   NSAttributedString *attributedText;
/**
 *  字符层数组。可以通过此数组来控制各个字符来实现你想要的效果。
 */
@property(nonatomic, strong, readonly) NSArray<CATextLayer*> *layerArray;
/**
 *  @brief  刷新图层，一般用在设置attributedText后修改属性使用，其他地方不需调用。如果attributedText为nil则该函数没有任何效果。
 *  @param  animation  YES-有动画效果，NO-无动画效果。
 */
-(void)refreshLayer:(BOOL)animation;

/**
 *  水平方向对齐，默认值为XPQLabelHorizontalAlignmentLeft。改变时没有动画效果，如果需要动画效果可以参考setTextHorizontalAlignment:animation。
 */
@property(nonatomic) XPQLabelHorizontalAlignment textHorizontalAlignment;
/**
 *  垂直方向对齐，默认值为XPQLabelVerticalAlignmentCenter。改变时没有动画效果，如果需要动画效果可以参考setTextVerticalAlignment:animation。
 */
@property(nonatomic) XPQLabelVerticalAlignment textVerticalAlignment;
/**
 *  @brief  设置文本水平对齐方向
 *  @param textHorizontalAlignment 水平对齐方向。
 *  @param animation               YES-有动画效果，NO-无动画效果。
 */
-(void)setTextHorizontalAlignment:(XPQLabelHorizontalAlignment)textHorizontalAlignment animation:(BOOL)animation;
/**
 *  @brief  设置文本垂直对齐方向
 *  @param textVerticalAlignment 垂直对齐方向。
 *  @param animation             YES-有动画效果，NO-无动画效果。
 */
-(void)setTextVerticalAlignment:(XPQLabelVerticalAlignment)textVerticalAlignment animation:(BOOL)animation;
@end

@interface XPQLabel (Path)

/**
 *  字符路径
 */
@property(nonatomic) XPQLabelPath *path;

-(void)setPath:(XPQLabelPath *)path rotate:(BOOL)rotate animation:(BOOL)animation;
@end

#pragma mark - 文本动画效果
/**
 *  这个分类主要是实现一些动画效果。
 */
@interface XPQLabel (Animation)
/**
 *  @brief  启动跳动动画
 *  @param height   跳动幅度
 *  @param beatTime 跳一次所用时间
 *  @param banTime  两次跳动之间的禁止时间
 *  @param stepTime 两个字符之间跳动的间隔时间
 */
-(void)startBeatAnimationWithBeatHeight:(CGFloat)height beatTime:(NSTimeInterval)beatTime banTime:(NSTimeInterval)banTime stepTime:(NSTimeInterval)stepTime;
/**
 *  @brief  停止跳动动画
 */
-(void)stopBeatAnimation;

/**
 *  @brief  启动抖动动画
 */
-(void)startWiggleAnimation;

/**
 *  @brief  停止抖动动画
 */
-(void)stopWiggleAnimation;
@end


#pragma mark - 文本显示隐藏动画效果
/**
 动画移动方向
 */
typedef enum : NSUInteger {
    XPQLabelAnimationDirectionDown,
    XPQLabelAnimationDirectionUp,
    XPQLabelAnimationDirectionLeft,
    XPQLabelAnimationDirectionRight,
} XPQLabelAnimationDirection;

/**
 *  这个分类主要是实现显示和隐藏过程中的动画效果。
 */
@interface XPQLabel (ShowAndHide)
/**
 *  @brief  启动显示动画（直线移动）。
 *  @param direction 移动方向。
 *  @param duration  单个字符移动时间。
 *  @param bounce    弹性系数，反弹距离为bounce * 字体大小。
 *  @param stepTime  两个字符之间动画间隔时间。
 */
-(void)startShowWithDirection:(XPQLabelAnimationDirection)direction duration:(NSTimeInterval)duration bounce:(CGFloat)bounce stepTime:(NSTimeInterval)stepTime;
/**
 *  @brief  停止显示动画（直线移动）。
 */
-(void)stopDropShow;

/**
 *  @brief  启动隐藏动画（直线移动）。
 *  @param direction 移动方向。
 *  @param duration  单个字符移动时间。
 *  @param stepTime  两个字符之间动画间隔时间。
 */
-(void)startHideWithDirection:(XPQLabelAnimationDirection)direction duration:(NSTimeInterval)duration stepTime:(NSTimeInterval)stepTime;
/**
 *  @brief  停止隐藏动画（直线移动）。
 */
-(void)stopDropHide;

/**
 *  @brief  启动显示动画（固定位置）。
 *  @param transform 显示过程中变化值，此值是指开始时的状态。
 *  @param duration  单个字符持续时间。
 *  @param stepTime  两个字符之间动画间隔时间。
 */
-(void)startFixedShowWithTransform:(CATransform3D *)transform duration:(NSTimeInterval)duration stepTime:(NSTimeInterval)stepTime;
/**
 *  @brief  停止显示动画（固定位置）。
 */
-(void)stopFixedShow;

/**
 *  @brief  启动隐藏动画（固定位置）。
 *  @param transform 隐藏过程中变化值，此值是指结束时的状态。
 *  @param duration  单个字符持续时间。
 *  @param stepTime  两个字符之间动画间隔时间。
 */
-(void)startFixedHideWithTransform:(CATransform3D *)transform duration:(NSTimeInterval)duration stepTime:(NSTimeInterval)stepTime;
/**
 *  @brief  停止隐藏动画（固定位置）。
 */
-(void)stopFixedHide;
@end




/*
#import "ViewController.h"
#import "XPQLabel.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet XPQLabel *stringLabel;
@property (weak, nonatomic) IBOutlet XPQLabel *attributedLabel;

@property (weak, nonatomic) IBOutlet UISegmentedControl *pathAnimationSegment;
@property (weak, nonatomic) IBOutlet UISegmentedControl *pathRotateSegment;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    _stringLabel.text = @"这里是一串普通的文本文字。";
    
    NSMutableAttributedString *attriString = [[NSMutableAttributedString alloc] initWithString:@"this is attributed string."];
    //把this的字体颜色变为红色
    [attriString addAttribute:(NSString *)kCTForegroundColorAttributeName
                        value:(id)[UIColor redColor].CGColor
                        range:NSMakeRange(0, 4)];
    //把is变为绿色
    [attriString addAttribute:(NSString *)kCTForegroundColorAttributeName
                        value:(id)[UIColor greenColor].CGColor
                        range:NSMakeRange(5, 2)];
    //改变this的字体，value必须是一个CTFontRef
    [attriString addAttribute:(NSString *)kCTFontAttributeName value:(id)CFBridgingRelease(CTFontCreateWithName((CFStringRef)[UIFont boldSystemFontOfSize:12].fontName, 20, NULL)) range:NSMakeRange(8, 10)];
    //给this加上下划线，value可以在指定的枚举中选择
    [attriString addAttribute:(NSString *)kCTUnderlineStyleAttributeName
                        value:(id)[NSNumber numberWithInt:kCTUnderlineStyleDouble]
                        range:NSMakeRange(19, 6)];
    
    _attributedLabel.attributedText = attriString;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)onHorizontalAlignmentChange:(UISegmentedControl *)sender {
    BOOL animation = (self.pathAnimationSegment.selectedSegmentIndex == 0);
    // 可以直接通过textHorizontalAlignment属性设置，默认是不带动画。
    switch (sender.selectedSegmentIndex) {
        case 0:
            [self.stringLabel setTextHorizontalAlignment:XPQLabelHorizontalAlignmentLeft animation:animation];
            [self.attributedLabel setTextHorizontalAlignment:XPQLabelHorizontalAlignmentLeft animation:animation];
            break;
            
        case 1:
            [self.stringLabel setTextHorizontalAlignment:XPQLabelHorizontalAlignmentCenter animation:animation];
            [self.attributedLabel setTextHorizontalAlignment:XPQLabelHorizontalAlignmentCenter animation:animation];
            break;
            
        case 2:
            [self.stringLabel setTextHorizontalAlignment:XPQLabelHorizontalAlignmentRight animation:animation];
            [self.attributedLabel setTextHorizontalAlignment:XPQLabelHorizontalAlignmentRight animation:animation];
            break;
        default:
            break;
    }
}

- (IBAction)onVerticalAlignmentChange:(UISegmentedControl *)sender {
    BOOL animation = (self.pathAnimationSegment.selectedSegmentIndex == 0);
    // 可以直接通过textVerticalAlignment属性设置，默认是不带动画。
    switch (sender.selectedSegmentIndex) {
        case 0:
            [self.stringLabel setTextVerticalAlignment:XPQLabelVerticalAlignmentUp animation:animation];
            [self.attributedLabel setTextVerticalAlignment:XPQLabelVerticalAlignmentUp animation:animation];
            break;
            
        case 1:
            [self.stringLabel setTextVerticalAlignment:XPQLabelVerticalAlignmentCenter animation:animation];
            [self.attributedLabel setTextVerticalAlignment:XPQLabelVerticalAlignmentCenter animation:animation];
            break;
            
        case 2:
            [self.stringLabel setTextVerticalAlignment:XPQLabelVerticalAlignmentDown animation:animation];
            [self.attributedLabel setTextVerticalAlignment:XPQLabelVerticalAlignmentDown animation:animation];
            break;
            
        default:
            break;
    }
}
- (IBAction)onSetPath:(UISegmentedControl *)sender {
    BOOL rotate = (self.pathRotateSegment.selectedSegmentIndex == 0);
    BOOL animation = (self.pathAnimationSegment.selectedSegmentIndex == 0);
    // 可以直接通过path属性设置，默认是带旋转带动画。
    switch (sender.selectedSegmentIndex) {
        case 0:
            [self.stringLabel setPath:nil rotate:rotate animation:animation];
            [self.attributedLabel setPath:nil rotate:rotate animation:animation];
            break;
            
        case 1: {
            XPQLabelPath *path = [XPQLabelPath pathForBeginPoint:CGPointMake(10.0, 10.0)];
            [path addLineToPoint:CGPointMake(250.0, 50.0)];
            [self.stringLabel setPath:path rotate:rotate animation:animation];
            XPQLabelPath *path2 = [XPQLabelPath pathForBeginPoint:CGPointMake(10.0, 50.0)];
            [path2 addLineToPoint:CGPointMake(220.0, 10.0)];
            [self.attributedLabel setPath:path2 rotate:rotate animation:animation];
        }
            break;
            
        case 2: {
            XPQLabelPath *path = [XPQLabelPath pathForBeginPoint:CGPointMake(20.0, 70.0)];
            [path addArcWithCentrePoint:CGPointMake(90.0, 70.0) angle:-M_PI];
            [self.stringLabel setPath:path rotate:rotate animation:animation];
            [self.attributedLabel setPath:path rotate:rotate animation:animation];
        }
            break;
            
        case 3: {
            XPQLabelPath *path = [XPQLabelPath pathForBeginPoint:CGPointMake(20.0, 60.0)];
            [path addCurveToPoint:CGPointMake(300.0, 60.0) anchorPoint:CGPointMake(100.0, 0.0)];
            [self.stringLabel setPath:path rotate:rotate animation:animation];
            [self.attributedLabel setPath:path rotate:rotate animation:animation];
        }
            break;
        default:
            break;
    }
}

- (IBAction)onEnterAnmation1:(id)sender {
    [self.stringLabel startShowWithDirection:XPQLabelAnimationDirectionDown duration:0.5 bounce:0.0 stepTime:0.2];
    [self.attributedLabel startShowWithDirection:XPQLabelAnimationDirectionLeft duration:0.5 bounce:0.0 stepTime:0.2];
}

- (IBAction)onExitAnmation1:(id)sender {
    [self.stringLabel startHideWithDirection:XPQLabelAnimationDirectionLeft duration:0.5 stepTime:0.2];
    [self.attributedLabel startHideWithDirection:XPQLabelAnimationDirectionDown duration:0.5 stepTime:0.2];
}

- (IBAction)onEnterAnmation2:(id)sender {
    CATransform3D transform = CATransform3DScale(CATransform3DIdentity, 0.0, 0.0, 1.0);
    [self.stringLabel startFixedShowWithTransform:&transform duration:1.0 stepTime:0.1]; CATransform3DRotate(CATransform3DIdentity, 2 * M_PI, 0.0, 0.0, 1.0);
    [self.attributedLabel startFixedShowWithTransform:&transform duration:1.0 stepTime:0.1];
}

- (IBAction)onExitAnmation2:(id)sender {
    CATransform3D transform = CATransform3DScale(CATransform3DIdentity, 0.0, 0.0, 1.0);
    [self.stringLabel startFixedHideWithTransform:&transform duration:1.0 stepTime:0.1];
    [self.attributedLabel startFixedHideWithTransform:&transform duration:1.0 stepTime:0.1];
}

*/